

#include "GLFont.h"
#include <algorithm>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
#include <boost/make_shared.hpp>
#include <GL/glu.h>

#include <FTGL/ftgl.h>
#include <map>
#include <string>
#include <log/log.h>
std::string get_ttf_path( const char* name );




class FTGLFontManager
{
	public:
		typedef std::map<std::string, GLFONT> FontList;
		enum FONT_TYPE{ BITMAP_FONT,BUFFER_FONT,EXTURDE_FONT,OUTLINE_FONT,PIXMAP_FONT,POLYGON_FONT,TEXTURE_FONT};
    public:
        // NOTE
        // This is shown here for brevity. The implementation should be in the source
        // file otherwise your compiler may inline the function resulting in
        // multiple instances of FTGLFontManager
        static FTGLFontManager& Instance()
        {
            static FTGLFontManager tm;
            return tm;
        }

        ~FTGLFontManager()
        {
        }


        GLFONT GetFont(const char *filename, int type, int faceSize,float depth,float outset)
        {
            char buf[256];
            sprintf(buf, "%s-%d-%d-%g-%g", filename, type, faceSize,depth,outset);
            std::string fontKey = std::string(buf);
            auto result = fonts.find(fontKey);
            if(result != fonts.end())
            {
                return result->second;
            }
        	std::string fullpath = get_ttf_path(filename);
        	std::shared_ptr<FTFont> font;
        	switch(type)
        	{
				case BITMAP_FONT:
					font = std::make_shared<FTBitmapFont>(fullpath.c_str());
					break;
				case BUFFER_FONT:
					font = std::make_shared<FTBufferFont>(fullpath.c_str());
					break;
				case EXTURDE_FONT:
					font = std::make_shared<FTExtrudeFont>(fullpath.c_str());
					break;
				case OUTLINE_FONT:
					font = std::make_shared<FTOutlineFont>(fullpath.c_str());
					break;
				case PIXMAP_FONT:
					font = std::make_shared<FTPixmapFont>(fullpath.c_str());
					break;
				case POLYGON_FONT:
					font = std::make_shared<FTPolygonFont>(fullpath.c_str());
					break;
				case TEXTURE_FONT:
					font = std::make_shared<FTTextureFont>(fullpath.c_str());
					break;
				return GLFONT();
        	};
        	if( font->Error() )
        	{
        		logs::error_log("Unkown font: %s",fullpath.c_str());
        		throw (std::string("unkown font:")+fullpath).c_str();
        		return GLFONT();
        	}
        	font->FaceSize(faceSize);
            font->Depth(depth);
            font->Outset(outset);
            font->CharMap(ft_encoding_unicode);

            fonts[fontKey] = font;

            return font;
        }


    private:
        // Hide these 'cause this is a singleton.
        FTGLFontManager(){}
        FTGLFontManager(const FTGLFontManager&){};
        FTGLFontManager& operator = (const FTGLFontManager&){ return *this; };

        // container for fonts
        FontList fonts;
};

GLFONT CreateFTBitmapFont(const char* path,int faceSize,float depth,float outset)
{
	return FTGLFontManager::Instance().GetFont( path, FTGLFontManager::BITMAP_FONT,faceSize, depth, outset);
}

GLFONT CreateFTBufferFont(const char* path,int faceSize,float depth,float outset)
{
	return FTGLFontManager::Instance().GetFont( path, FTGLFontManager::BUFFER_FONT,faceSize, depth, outset);
}
GLFONT CreateFTExtrudeFont(const char* path,int faceSize,float depth,float outset)
{
	return FTGLFontManager::Instance().GetFont( path, FTGLFontManager::EXTURDE_FONT,faceSize, depth, outset);

}
GLFONT CreateFTOutlineFont(const char* path,int faceSize,float depth,float outset)
{
	return FTGLFontManager::Instance().GetFont( path, FTGLFontManager::OUTLINE_FONT,faceSize, depth, outset);

}

GLFONT CreateFTPixmapFont(const char* path,int faceSize,float depth,float outset)
{
	return FTGLFontManager::Instance().GetFont( path, FTGLFontManager::PIXMAP_FONT,faceSize, depth, outset);

}
GLFONT CreateFTPolygonFont(const char* path,int faceSize,float depth,float outset)
{
	return FTGLFontManager::Instance().GetFont( path, FTGLFontManager::POLYGON_FONT,faceSize, depth, outset);

}
GLFONT CreateFTTextureFont(const char* path,int faceSize,float depth,float outset)
{
	return FTGLFontManager::Instance().GetFont( path, FTGLFontManager::TEXTURE_FONT,faceSize, depth, outset);
}
